home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / sml_nj / 93src.lha / src / coder / coder.sml < prev    next >
Encoding:
Text File  |  1993-01-27  |  24.9 KB  |  840 lines

  1. (* coder.sml
  2.  *
  3.  * Copyright 1989 by AT&T Bell Laboratories
  4.  *
  5.  * This is a machine independent code scheduler for RISC machines with 32-bit
  6.  * instructions.  We assume that the machine has delayed branches.
  7.  *
  8.  * AUTHOR:  John Reppy
  9.  *        Cornell University
  10.  *        Ithaca, NY 14853
  11.  *        jhr@cs.cornell.edu
  12.  *
  13.  * Also fiddled with by Lal George, Andrew Appel
  14.  *)
  15.  
  16. signature CODER =
  17. sig
  18.     eqtype label
  19.     type 'label instruction
  20.     type 'label sdi
  21.  
  22.     val baseLab : label   (* The symbolic base address of the current code block. *)
  23.  
  24.     val newLabel : unit -> label
  25.     val define : label -> unit
  26.  
  27.     val emitLong : int -> unit
  28.     val emitString : string -> unit
  29.     exception BadReal of string
  30.     val emitReal : string -> unit
  31.     val emitLabel : (label * int) -> unit
  32.     (* L3: emitLabel(L2, k) is equivalent to L3: emitLong(k+L2-L3) *)
  33.  
  34.     val mark : unit -> unit
  35.  
  36.     val emit : label instruction -> unit
  37.     val emitSDI : label sdi -> unit
  38.  
  39.     val comment : string -> unit
  40.  
  41.     val finish : unit -> unit
  42.  
  43. end (* signature CODER *)
  44.  
  45. functor Coder (structure M : MACHINSTR and E : EMITTER
  46.            sharing type M.instruction = E.instruction
  47.            and type M.info = E.info) : CODER = 
  48. struct
  49.  
  50.     structure V = Vector
  51.     open M
  52.     val error = ErrorMsg.impossible
  53.  
  54.     abstraction Label : sig eqtype label
  55.                 val reset : unit -> unit
  56.                 val newLabel : unit -> label
  57.                 val nameOf : label -> string
  58.                 val numberOf: label -> int
  59.                 val count : unit -> int
  60.                 val baseLab : label
  61.             end =
  62.     struct 
  63.     type label = int
  64.     val cnt = ref 1
  65.     fun reset() = cnt := 1
  66.     fun newLabel() = let val x = !cnt in cnt := x+1; x end
  67.     fun nameOf (id:label) = "L" ^ (makestring id)
  68.     fun numberOf id = id
  69.     fun count() = !cnt
  70.     val baseLab = 0
  71.     end
  72.  
  73.     open Label
  74.  
  75.     datatype data
  76.       = LABEL of label
  77.       | MARK
  78.       | LONGconst of int
  79.       | STRINGconst of string
  80.       | REALconst of string
  81.       | ADDRconst of (label * int)
  82.  
  83.     datatype block =
  84.     CODEBLK  of {instrs: label instruction list, 
  85.              lo: int,        (* min size (bytes)*)
  86.              hi:int}        (* max size (bytes)*)
  87.       | DATABLK  of (data * int) list    (* data and its size (bytes) *)
  88.       | SDIBLK   of {sdi:label sdi, 
  89.              lo:int ref,    (* expansion under min conditions *)
  90.              hi:int ref,    (* expansion under max conditions *)
  91.              loLoc:int ref,    (* location counter under min cond *)
  92.                  hiLoc:int ref}    (* location counter under max cond *)
  93.       | BASICBLK of {cblks: block list, (* CODEBLK + SDIBLK *)
  94.              bbsize: int}    (* size assuming perf.sched+minsdi *)
  95.       | SCHEDBLK of label instruction Vector.vector
  96.  
  97.     val codeList = ref [DATABLK[(LABEL baseLab,0)]]
  98.  
  99.     fun reset () = (Label.reset(); codeList := [DATABLK[(LABEL baseLab,0)]])
  100.  
  101.     fun dataListSize dl =
  102.     let fun sum ([],acc) = acc
  103.           | sum ((_,size)::dl,acc) = sum(dl,acc+size)
  104.     in sum (dl,0)
  105.     end
  106.  
  107.     fun emit I = let
  108.     val nopsSize = 4 * mayNeedNop I
  109.     val newCList = 
  110.          (case !codeList  
  111.         of CODEBLK{instrs,hi,lo}::blks => 
  112.              CODEBLK{instrs=I::instrs,lo=lo+4,hi=hi+4+nopsSize}::blks
  113.          | blks => CODEBLK{instrs=[I],lo=4,hi=4+nopsSize}::blks)
  114.       in
  115.       codeList := (case instrKind I 
  116.                      of IK_JUMP => DATABLK[]::newCList
  117.                   | _ => newCList)
  118.       end
  119.  
  120.     fun emitData (D,size) = 
  121.     (codeList := (case !codeList
  122.               of DATABLK dl::blks => 
  123.                 DATABLK((D,size)::dl)::blks
  124.                | blks => DATABLK[(D,size)]::blks))
  125.  
  126.     fun padString s = (case ((size s) mod 4)
  127.        of 0 => s
  128.         | 1 => (s ^ "\000\000\000")
  129.         | 2 => (s ^ "\000\000")
  130.         | 3 => (s ^ "\000")
  131.         | _ => error "")
  132.  
  133.  
  134.     fun emitLong i = emitData (LONGconst i, 4)
  135.  
  136.     fun emitString s = let val s' = padString s
  137.                in
  138.                emitData (STRINGconst s',size s')
  139.                end
  140.  
  141.     exception BadReal of string        (* not used yet! *)
  142.  
  143.     fun emitReal r = emitData(REALconst r, 8)
  144.  
  145.     fun emitLabel args = emitData(ADDRconst args, 4)
  146.  
  147.     fun define (lab) = emitData(LABEL lab, 0)
  148.  
  149.     fun mark () = emitData(MARK, 4)
  150.  
  151.     fun emitSDI I = let
  152.       val nd = SDIBLK{sdi=I,lo=ref 0,hi=ref 0,loLoc=ref 0,hiLoc=ref 0}
  153.     in codeList := (if isSdiBranch I then  DATABLK[]::nd:: !codeList
  154.             else nd:: !codeList)
  155.     end
  156.  
  157.     val comment = E.comment
  158.  
  159. fun finish() =
  160. let val labelmap = Array.array(count(),0)
  161.     val labinfo = INFO{addrOf = fn lab => Array.sub(labelmap,(numberOf lab)),
  162.                nameOf = nameOf}
  163.     val sizeOf = sizeOf labinfo
  164.     val e_define = E.define labinfo
  165.     val e_emitAddr = E.emitAddr labinfo
  166.     val e_emitInstr = E.emitInstr labinfo
  167.     val expand = M.expand labinfo
  168.  
  169.     (** label calculations **)
  170.  
  171.     local
  172.       datatype labelExtremes = LO | HI
  173.  
  174.       (** compute worst case size of sdi **)
  175.       fun worstSdiSize(sdi,loc) = let
  176.             val (_,size) = sizeOf(sdi,loc)
  177.         fun worstCaseExp([],acc) = acc
  178.           | worstCaseExp(i::instrs,acc) = 
  179.             (case instrKind i
  180.            of IK_JUMP => 
  181.                 if branchDelayedArch then worstCaseExp(instrs,acc+8)
  182.             else worstCaseExp(instrs,acc+4)
  183.             | _ => worstCaseExp(instrs,acc+4+(4*mayNeedNop i)))
  184.           in
  185.           (size, worstCaseExp (expand(sdi,size,loc),0))
  186.           end
  187.  
  188.      (* initialize labels so that they are as close together.
  189.       * returns: size of blks. 
  190.       *)
  191.       fun init([],loc) = loc
  192.     | init(CODEBLK{lo,...}::blks,loc) = init(blks,loc+lo)
  193.     | init(DATABLK dl::blks,loc) = 
  194.       let fun initData([],loc) = loc
  195.         | initData((LABEL lab,_)::dl,loc) = 
  196.             (Array.update(labelmap, numberOf lab, loc); initData(dl,loc))
  197.         | initData((_,size)::dl,loc) = initData(dl,loc+size)
  198.       in
  199.           init(blks,initData(dl,loc))
  200.       end
  201.     | init(SDIBLK{sdi,lo,hi,loLoc,...}::blks,loc) = 
  202.       let val size = M.minSize sdi
  203.       in lo:=size; hi:=size; loLoc:=loc; init(blks,loc+size)
  204.       end
  205.     | init(BASICBLK{bbsize,...}::blks,loc) = init(blks, bbsize+loc)
  206.     | init(SCHEDBLK instrs::blks,loc) = init(blks,loc+4*V.length instrs)
  207.  
  208.      (* fixBlocks
  209.       *    - iterates to a fixpoint computing labels.  
  210.       *    - side-effects labels and returns code size.
  211.       *)
  212.       fun adjust(blks,which) = let
  213.       fun fixBlocks size = let
  214.           fun fixLabels([],loc) = loc
  215.         | fixLabels(DATABLK dl::rest,loc) = 
  216.           let 
  217.               fun initData([],loc') = loc'
  218.             | initData((LABEL lab,_)::dl,loc') =
  219.                 (Array.update(labelmap, numberOf lab, loc');
  220.                  initData(dl,loc'))
  221.             | initData((_,size)::dl,loc') = initData(dl,loc'+size)
  222.           in 
  223.               fixLabels(rest,initData(dl,loc))
  224.           end
  225.         | fixLabels(BASICBLK{cblks,...}::rest,loc) = 
  226.             fixLabels(rest,fixLabels(cblks,loc)) 
  227.         | fixLabels(CODEBLK{hi,lo,...}::rest,loc) = 
  228.           (case which 
  229.              of HI => fixLabels(rest,hi+loc) 
  230.               | LO => fixLabels(rest,lo+loc))
  231.         | fixLabels(SDIBLK{sdi,hi,lo,hiLoc,loLoc,...}::rest,loc) = 
  232.           (case which 
  233.            of LO => let val (_,size) = sizeOf(sdi,loc)
  234.                 in 
  235.                 loLoc:=loc;
  236.                 if size > (!lo) then lo := size else ();
  237.                 fixLabels(rest,max(!lo,size)+loc)
  238.                 end
  239.                    | HI => let val (size,trueSize) = worstSdiSize(sdi,loc)
  240.                in 
  241.                    hiLoc:=loc;
  242.                    if size > (!hi) then hi:=size else ();
  243.                    fixLabels(rest,trueSize+loc)
  244.                end
  245.           (* endcase *))
  246.         | fixLabels(SCHEDBLK instrs::rest,loc) =
  247.             fixLabels(rest,loc+4*V.length instrs)
  248.  
  249.           val newSize =  fixLabels(blks,0)
  250.         in
  251.         if newSize <> size then  fixBlocks newSize
  252.         else newSize
  253.         end
  254.         in 
  255.         fixBlocks (init(blks,0))
  256.         end
  257.     in
  258.     fun adjustLow blks = adjust(blks,LO)
  259.     fun adjustHigh blks = adjust(blks,HI)
  260.     end (*local*)
  261.  
  262.  
  263.     (** Instruction scheduling and machine code emission **)
  264.  
  265.     datatype instr_nd         (* Nodes in the resource dependency graph *)
  266.       = IND of {
  267.     id : int,                   (* unique id for equality testing *)
  268.     instr : label instruction,        (* The instruction *)
  269.     nsuccs : int,               (* The number of successors *)
  270.     succs : instr_nd list ref,
  271.     maxpathlen : int,           (* Length of the longest path to leaf. *)
  272.     npreds : int ref,           (* The number of predecessors *)
  273.         predLst : instr_nd list ref    (* list of predecessor nodes *)
  274.       }
  275.  
  276.     fun member (IND{id = x, ...}, lst) = let
  277.       fun mem nil = false
  278.         | mem (IND{id = y, ...}::rest) = ((x = y) orelse (mem rest))
  279.       in
  280.         mem lst
  281.       end
  282.  
  283.     fun merge (nil, lst) = lst
  284.       | merge (nd :: rest, lst) = if (member(nd, lst))
  285.       then merge (rest, lst)
  286.       else merge (rest, nd :: lst)
  287.  
  288.  
  289.  
  290.   (* Schedule and emit the instructions of a straight-line block of code. *)    
  291.     fun schedBB (exitInstr, instrs) = let
  292.  
  293.     val exitDep = case exitInstr
  294.          of NONE => (fn _ => false)
  295.           | (SOME e) => let
  296.               val (exitUses, exitDefs) = rUseDef e
  297.               val f = exists(fn r => (exists (fn x => (r = x)) exitUses))
  298.               val g = exists(fn r => (exists (fn x => (r = x)) exitDefs))
  299.               in
  300.             fn I => let
  301.                   val (u, d) = rUseDef I
  302.                   in
  303.                 (f d) orelse (g d) orelse (g u)
  304.                   end
  305.               end
  306.  
  307.     (* for debugging *)
  308.     fun printDag (n,roots) =  let
  309.         val visited =  Array.array(n+1,false)
  310.         fun printSuccs [] = System.Print.say "\n"
  311.           | printSuccs (IND nd::rest) = 
  312.         (app System.Print.say ["(",makestring (#id nd),",",
  313.                 makestring (#nsuccs nd), ",",
  314.                 makestring (#maxpathlen nd), ",",
  315.                 makestring (exitDep (#instr nd)), ",",
  316.                 makestring (!(#npreds nd)), ")"];
  317.          printSuccs rest)
  318.         fun visit (IND nd) = let
  319.         val id = #id nd
  320.           in
  321.           app System.Print.say [makestring(#id nd), " :: "];
  322.           printSuccs(!(#succs nd));
  323.           Array.update(visited,#id nd,true);
  324.           app (fn IND nd => if Array.sub(visited,#id nd) then ()
  325.                     else visit (IND nd)) (!(#succs nd))
  326.           end
  327.       in
  328.           app (fn IND nd => if Array.sub(visited,#id nd) then () 
  329.                 else visit (IND nd)) roots
  330.       end
  331.  
  332.     (* make a new instr_nd *)
  333.        fun mkINd (n, I, nil) =
  334.          IND{id = n, instr = I,
  335.            nsuccs = 0, succs = ref nil, 
  336.            maxpathlen = latency I, npreds = ref 0, predLst=ref nil}
  337.      | mkINd (n, I, succLst) = let
  338.          val lat = latency I
  339.          fun f (nil, len, mpl) = (len, mpl)
  340.            | f (IND{instr, maxpathlen, ...} :: rest, len, mpl) =
  341.            f (rest,len+1,if maxpathlen > mpl then  maxpathlen else mpl)
  342.          val (len, mpl) = f (succLst, 0, 0)
  343.        in
  344.            IND{id = n, instr = I,
  345.            nsuccs = len, succs = ref succLst, 
  346.            maxpathlen = mpl+lat, npreds = ref 0, predLst=ref nil}
  347.        end
  348.     (* resource use/def vectors *)
  349.        val lastUse = Array.array (numResources, nil)
  350.        val lastDef = Array.array (numResources, nil)
  351.     (* find resource dependencies *)
  352.        fun findDeps rsrc = let
  353.        fun add (nil, lst) = lst
  354.          | add (r :: rest, lst) = 
  355.            add (rest, merge(Array.sub(rsrc,r), lst))
  356.      in
  357.          add
  358.      end
  359.        val findUseDeps = findDeps lastUse
  360.        val findDefDeps = findDeps lastDef
  361.     (* update resource use/def vectors *)
  362.        fun updateUseDefs nd = let
  363.        val ndl = [nd]
  364.        val updateUses =
  365.              app (fn r => Array.update(lastUse, r, 
  366.                        nd::(Array.sub(lastUse,r))))
  367.        val updateDefs =
  368.               app (fn r => (Array.update(lastDef, r, ndl); 
  369.                    Array.update(lastUse, r, nil)))
  370.      in
  371.          fn (ruses, rdefs) => (updateDefs rdefs; updateUses ruses)
  372.      end
  373.     (* extract the dependency graph roots from the use/def vectors *)
  374.        fun roots () = let
  375.        fun isRoot (IND{npreds, ...}) = (!npreds = 0)
  376.        fun rootsOf (nil, lst) = lst
  377.          | rootsOf (nd::rest, lst) = if (isRoot nd)
  378.                      then rootsOf (rest, nd::lst)
  379.                      else rootsOf (rest, lst)
  380.        fun mergeRoots (~1, lst) = lst
  381.          | mergeRoots (i, lst) = let
  382.          val rlst = rootsOf (merge (Array.sub(lastDef,i), 
  383.                         Array.sub(lastUse,i)), nil)
  384.            in
  385.            mergeRoots (i-1, merge (rlst, lst))
  386.            end
  387.        fun filterBranch [] = []
  388.          | filterBranch ((nd as IND{instr,...})::rest) = 
  389.            if instrKind instr = IK_JUMP then filterBranch rest
  390.            else nd::filterBranch rest
  391.      in
  392.          filterBranch(mergeRoots (numResources-1, nil))
  393.      end (* roots *)
  394.  
  395.        fun buildDepGraph instrs = let
  396.        fun incPreds (nil,_) = ()
  397.          | incPreds (IND{npreds,predLst,...} :: rest, nd) = 
  398.              (npreds := !npreds + 1; 
  399.           predLst:=nd:: (!predLst);
  400.           incPreds (rest,nd))
  401.  
  402.        fun doInstrs (nil, n) = n
  403.          | doInstrs (I :: rest, n) = 
  404.            (case (instrKind I)
  405.           of IK_NOP => ()
  406.                | _ => 
  407.              let val (ruses, rdefs) = rUseDef I
  408.              (* find use/def, def/use and def/def dependencies *)
  409.              val succLst = findUseDeps (rdefs,
  410.                       findDefDeps(rdefs,
  411.                         findDefDeps (ruses, nil)))
  412.              val nd = mkINd (n, I, succLst)
  413.              in
  414.              incPreds (succLst,nd);
  415.              updateUseDefs nd (ruses, rdefs)
  416.              end
  417.              (* end case *);
  418.              doInstrs (rest, n+1))
  419.      in
  420.          doInstrs(instrs,0)
  421.      end (* buildDepGraph *)
  422.  
  423.        fun mkNops n = if n <= 0 then [] else nop :: mkNops (n-1)
  424.  
  425.        fun chooseInstr (nd::ndl) = let
  426.        fun orderInstrPair (nd1 as IND a, nd2 as IND b) = let
  427.            fun pathBasis () = let 
  428.            val p1 = #maxpathlen a
  429.            val p2 = #maxpathlen b
  430.          in
  431.              if p1 = p2 then NONE
  432.              else if p1 > p2 then SOME(nd1,nd2)
  433.               else SOME(nd2,nd1)
  434.          end
  435.            fun succBasis () = let
  436.            val n1 = #nsuccs a
  437.            val n2 = #nsuccs b
  438.          in
  439.              if n1 > n2 then SOME(nd1,nd2)
  440.              else if n1 < n2 then SOME(nd2,nd1)
  441.               else NONE
  442.          end
  443.          in
  444.          case pathBasis () 
  445.            of SOME x => x
  446.             | NONE => 
  447.             (case succBasis () 
  448.                of SOME x => x
  449.                 | NONE => (nd1,nd2))
  450.          end
  451.        fun choose (choice,[],done) = (choice,done)
  452.          | choose (choice,nd::rest,done) = let
  453.          val (newChoice,reject) = orderInstrPair (choice,nd)
  454.            in
  455.            choose(newChoice,rest,reject::done)
  456.            end
  457.      in
  458.          choose (nd,ndl,[])
  459.      end
  460.  
  461.        fun enableSuccs([],[],candidates) = candidates
  462.      | enableSuccs(IND{succs,...}::rest,[],candidates) =
  463.          enableSuccs(rest,!succs,candidates)
  464.      | enableSuccs (nds,(nd as IND{npreds,instr,...})::rest,candidates) =
  465.        if instrKind instr = IK_JUMP
  466.            then enableSuccs(nds,rest,candidates)
  467.            else let
  468.                val n = !npreds
  469.              in
  470.          npreds:=n-1;
  471.          if n=1 then enableSuccs(nds,rest,nd::candidates)
  472.          else enableSuccs(nds,rest,candidates)
  473.          end
  474.  
  475.        (* 
  476.        ** Perform a time simulation of instructions 
  477.        ** to be executed 
  478.        *)
  479.        fun traverse ([],[],cl) = cl
  480.      | traverse ([], blocked, cl) = let
  481.         (* no root instructions *)
  482.          exception Advance
  483.  
  484.          fun advance [] = raise Advance 
  485.            | advance blocked = let
  486.          val infinity = 1000000
  487.          fun findMin([],ans) = ans
  488.            | findMin((_,t,lat)::rest,ans) = 
  489.              if lat-t < ans then findMin(rest,lat-t) 
  490.              else findMin(rest,ans)
  491.          fun advanceby(_,[],acc,blked) = (acc,blked)
  492.            | advanceby(N,(nd,t,lat)::rest,acc,blked) =
  493.              if t+N >= lat then advanceby(N,rest,nd::acc,blked)
  494.              else advanceby(N,rest,acc,(nd,t+N,lat)::blked)
  495.            in
  496.            advanceby(findMin(blocked,infinity),blocked,[],[])
  497.            end
  498.  
  499.          val (nds,blocked') = advance blocked
  500.          val candidates = enableSuccs(nds,[],[])
  501.        in
  502.            traverse(candidates,blocked',cl)
  503.        end
  504.      | traverse (candidates,[],cl) = let
  505.          val (nd as(IND{instr,succs,...}),newCandidates) =
  506.             chooseInstr candidates
  507.          val newCl = instr::cl
  508.          val instrLat = latency instr
  509.            in
  510.           if instrLat = 1 
  511.           then let 
  512.                   val newCandidates' = enableSuccs([nd],[],newCandidates)
  513.                 in
  514.             traverse(newCandidates',[],newCl)
  515.                 end
  516.           else traverse(newCandidates,[(nd,0,instrLat)],newCl)
  517.            end
  518.      | traverse (candidates,blocked,cl) = let
  519.          fun executeBlocked [] = ([],[])
  520.            | executeBlocked blocked = let
  521.            fun tick ([],ndl,blocked) = (ndl,blocked)
  522.              | tick ((nd,t,lat)::rest,ndl,blocked) =
  523.             if t+1 >= lat then tick(rest,nd::ndl,blocked)
  524.             else tick(rest,ndl,(nd,t+1,lat)::blocked)
  525.          in
  526.             tick(blocked,[],[])
  527.          end
  528.          val (nds,blocked') = executeBlocked blocked
  529.          val (nd as(IND{instr,succs,...}), newCandidates) = 
  530.              chooseInstr (enableSuccs(nds,[],candidates))
  531.          val instrLat = latency instr
  532.            in
  533.            traverse(newCandidates,(nd,0,instrLat)::blocked',instr::cl)
  534.        end
  535.  
  536.     fun findDelaySlotInstr roots = let
  537.         val visited = Array.array(length instrs+1,false)
  538.  
  539.         fun found (IND node) = let 
  540.         fun nopFree [] = true
  541.           | nopFree (IND x::xs) = 
  542.             if mayNeedNop(#instr x)>1 then false else nopFree xs
  543.           in
  544.           (#nsuccs node) = 0  
  545.           andalso latency (#instr node) <= 1 
  546.           andalso instrKind (#instr node) <> IK_JUMP 
  547.           andalso nopFree (!(#predLst node)) 
  548.           andalso not (exitDep (#instr node))
  549.           end
  550.  
  551.         fun visit (IND node) = 
  552.         if found (IND node) then SOME(IND node)
  553.         else let val adj = #succs node
  554.              in
  555.              Array.update(visited,#id node,true);
  556.              travRoots (!adj)
  557.              end
  558.  
  559.         and travRoots [] = NONE
  560.           | travRoots (IND nd::rest) =
  561.         if Array.sub(visited,#id nd) then travRoots rest
  562.         else (case visit (IND nd) 
  563.                 of NONE => travRoots rest
  564.                  | SOME n => SOME n)
  565.  
  566.        (** deletes branch delay instruction from DAG **)
  567.         fun deleteBranchDelayInstr (IND{id,predLst,...}) = let
  568.         exception BranchDelay
  569.         fun delete [] = []
  570.           | delete ((x as IND{id=id',...})::xs) = 
  571.             if id = id' then xs else x::delete xs
  572.           in
  573.           app (fn IND{succs,...} => succs := delete (!succs)) 
  574.               (!predLst)
  575.           end
  576.  
  577.         fun newRoots (IND ds, roots) = let
  578.         fun del ([],acc) = acc
  579.           | del (IND nd::rest, acc) =
  580.             if #id nd = #id ds then rest@acc
  581.             else del(rest, IND nd::acc)
  582.           in
  583.           del(roots,[])
  584.           end
  585.       in
  586.           case travRoots roots
  587.         of NONE     => (nop,roots)
  588.              | SOME(IND nd)    => (deleteBranchDelayInstr (IND nd);
  589.                     (#instr nd,newRoots(IND nd,roots)))
  590.       end(* findDelaySlotInstr *)
  591.  
  592.       (* inserts nops and reverses the instruction stream *)
  593.     fun insertNops instrs = let
  594.         fun insert ([],acc) = acc
  595.           | insert (x::xs,acc) = let
  596.           val n = needsNop(x,xs) 
  597.             in
  598.             if n > 0 then insert(xs,mkNops n @(x::acc))
  599.             else insert(xs,x::acc)
  600.             end
  601.           in
  602.           insert(instrs,[]) 
  603.           end
  604.  
  605.     fun assignOrder () = let
  606.           val roots = roots()
  607.         in
  608.           case roots
  609.         of [] => let val SOME e = exitInstr
  610.              in if branchDelayedArch then [nop, e] else [e]
  611.              end
  612.          | nds => 
  613.              (case exitInstr 
  614.             of NONE => let val cl = traverse(roots,[],[])
  615.                        val n = mayNeedNop (hd cl)
  616.                    in mkNops n @ cl
  617.                    end
  618.              | SOME e => 
  619.                if branchDelayedArch 
  620.                then let
  621.                    val (ds,roots') = findDelaySlotInstr roots
  622.                    val cl = traverse(roots',[],[])
  623.                  in
  624.                    ds::e::cl
  625.                  end
  626.                else  e::traverse(roots,[],[]))
  627.  
  628.         end
  629.       val allInstrs = case exitInstr of NONE => instrs
  630.                           | SOME e => e::instrs
  631.       val ndcount = buildDepGraph allInstrs
  632. (*        val _ = (printDag(ndcount,roots()); System.Print.say "\n\n")   *)
  633.       in
  634.       insertNops(assignOrder ())
  635.       end (* schedBB *)
  636.  
  637.     fun schedule blks = let 
  638.     fun isStable (BASICBLK{cblks,...}) =
  639.         let fun check [] = true
  640.           | check (CODEBLK _ ::blks) = check blks
  641.           | check (SDIBLK{lo,hi,...}::blks) = 
  642.               if (!lo) <> (!hi) then false else check blks
  643.           | check _ = error "Coder.isStable.check:"
  644.         in 
  645.         check cblks
  646.         end
  647.       | isStable _ = error "Coder.isStable:"
  648.  
  649.        (* replace stable blocks with their scheduled code sequence *)
  650.     fun schedStableBBs blks = let
  651.         fun collectCodeLists ([],[],acc) = acc
  652.           | collectCodeLists ([],codeList,acc) = let
  653.           val l = case codeList
  654.                     of I::rest => (case instrKind I
  655.                          of IK_JUMP => (SOME I,rest)
  656.                           | _     => (NONE,codeList))
  657.                  | _       => (NONE,codeList)
  658.                 in
  659.             l::acc
  660.                 end
  661.           | collectCodeLists (CODEBLK{instrs,...}::blks,l,acc) =
  662.           collectCodeLists (blks,instrs@l,acc)
  663.           | collectCodeLists (SDIBLK{sdi,lo,loLoc,...}::blks,l,acc) = let
  664.           fun insertSdiCode ([],l,acc) = collectCodeLists(blks,l,acc)
  665.             | insertSdiCode (i::instrs,l,acc) = 
  666.               (case instrKind i
  667.              of IK_JUMP => insertSdiCode(instrs,[],(SOME i,l)::acc)
  668.               | _       => insertSdiCode(instrs,i::l,acc))
  669.         in
  670.             insertSdiCode(expand(sdi,!lo,!loLoc),l,acc)
  671.         end
  672.           | collectCodeLists _ = error "collectCodeLists:"
  673.  
  674.         fun schedCodeLists ([],schd) = schd
  675.           | schedCodeLists (cl::codeList,schd) = 
  676.           schedCodeLists(codeList,schedBB cl @ schd)
  677.  
  678.         fun sched ([],bl,unstab,stab) = (rev bl,unstab,stab)
  679.           | sched ((blk as DATABLK dl)::rest,blks,u,s) = 
  680.           sched(rest,blk::blks,u,s)
  681.           | sched ((blk as SCHEDBLK _)::rest,blks,u,s) = 
  682.           sched(rest,blk::blks,u,s)
  683.           | sched ((blk as BASICBLK bb)::rest,blks,u,s) =
  684.         if not(isStable blk) 
  685.             then sched(rest,blk::blks,u+1,s)
  686.         else 
  687.                   let val codeList = collectCodeLists(#cblks bb,[],[])
  688.               val sch'd = schedCodeLists(codeList,[])
  689.               val newBlk = SCHEDBLK (V.vector sch'd)
  690.           in 
  691.               sched(rest,newBlk::blks,u,s+1)
  692.           end
  693.           | sched _ = error "Coder.schedule.schedStableBBs.sched:"
  694.  
  695.       in
  696.           sched(blks,[],0,0)
  697.       end (* schedStableBBs *)
  698.  
  699.         fun schedUnstableBBs blks = let
  700.         fun stabBB (BASICBLK{cblks,...}) = let
  701.           fun f [] =  ()
  702.             | f (CODEBLK _ ::blks) = f blks     
  703.             | f (SDIBLK{lo,hi,...}::blks) = 
  704.               (if !lo > !hi then hi := !lo else lo := !hi; 
  705.                f blks)
  706.             | f _ = error "Coder.schedUnstableBB.stabBB.f"
  707.         in 
  708.             f cblks
  709.         end
  710.           | stabBB _ = ()
  711.         val _ = app stabBB blks
  712.         val (newBlks,_,_) = schedStableBBs blks
  713.           in
  714.           newBlks
  715.       end
  716.  
  717.         fun schedLoop blks = let
  718.         val _ = adjustHigh blks
  719.         val _ = adjustLow blks
  720.         val (newBlks,nUnstab,nStab) = schedStableBBs blks
  721.           in
  722.           if nUnstab = 0 then newBlks
  723.           else if nStab <> 0 then schedLoop newBlks
  724.            else schedUnstableBBs newBlks
  725.       end
  726.     in
  727.     schedLoop blks
  728.     end (* schedule *)
  729.  
  730.     fun noSched blks = let
  731.     fun noSched ([],sched'd) = rev sched'd
  732.       | noSched ((dl as DATABLK _)::blks,sched'd) = noSched(blks,dl::sched'd)
  733.       | noSched (BASICBLK{cblks,...}::blks,sched'd) = 
  734.         let
  735.         fun insertInstr([],acc) = acc
  736.           | insertInstr(i::rest,acc) = let
  737.               fun mkNops 0 = []
  738.             | mkNops n = nop::mkNops(n-1)
  739.               val acc' = i::(mkNops(needsNop(i,acc)) @ acc)
  740.             in
  741.             case instrKind i
  742.               of IK_JUMP => if branchDelayedArch 
  743.                     then insertInstr(rest,nop::acc')
  744.                     else insertInstr(rest,acc')
  745.                | _          => insertInstr(rest,acc')
  746.                     end
  747.         fun noSchedBB([],acc) = rev acc
  748.           | noSchedBB(CODEBLK{instrs,...}::blks,acc) = 
  749.             noSchedBB(blks,insertInstr(rev instrs,acc))
  750.           | noSchedBB(SDIBLK{sdi,hi,hiLoc,...}::blks,acc) =
  751.             noSchedBB(blks,insertInstr(expand(sdi,!hi,!hiLoc),acc))
  752.           | noSchedBB _ = error "Coder.noSched.noSchedBB"
  753.         val newInstrs = noSchedBB(cblks,[])
  754.         val newBlk = SCHEDBLK (V.vector newInstrs)
  755.         in
  756.         noSched(blks,newBlk::sched'd)
  757.         end
  758.       | noSched _ = error "Coder.noSched"
  759.     val _ = adjustHigh blks
  760.       in
  761.       noSched(blks,[])
  762.       end
  763.  
  764.       fun mkBasicBlocks blks = let
  765.        fun collect(nil,acc,size) = (acc,nil,size)
  766.          | collect(blk::blks,acc,size) =
  767.            case blk
  768.              of SDIBLK{sdi,...} => collect(blks,blk::acc,size+minSize sdi)
  769.           | CODEBLK{instrs,lo,...} =>
  770.               collect(blks,blk::acc,size+lo)
  771.               | _ => (acc,blk::blks,size)
  772.        fun mkBBs([],acc) = acc
  773.          | mkBBs(blk::blks,acc) = let
  774.              fun f initSize = let
  775.                  val (cbs,rest,size) = collect(blks,[blk],initSize)
  776.                in
  777.                mkBBs(rest,BASICBLK{cblks=cbs,bbsize=size}::acc)
  778.                end
  779.                    in
  780.                case blk
  781.              of DATABLK dl => mkBBs(blks,DATABLK(rev dl)::acc)
  782.                   | CODEBLK{instrs,lo,...} => f lo
  783.               | SDIBLK{sdi,...} => f (minSize sdi)
  784.               | _ => error "coder/coder/mkBasicBlocks"
  785.                    end
  786.          in
  787.          mkBBs(blks,[])
  788.      end
  789.  
  790.        fun sched cl =  if (!System.Control.CG.scheduling) then schedule cl
  791.                else noSched cl
  792.        fun emitDataList nil = ()
  793.      | emitDataList (d :: rest) = (case (#1 (d:(data*int)))
  794.         of (LABEL lab) => e_define lab
  795.          | MARK => E.mark ()
  796.          | (LONGconst n) => E.emitLong n
  797.          | (STRINGconst s) => E.emitString s
  798.          | (REALconst r) => E.emitReal r
  799.          | (ADDRconst args) => e_emitAddr args
  800.            (* end case *);
  801.            emitDataList rest)
  802.        fun emitInstructions instrs = let
  803.          val len = V.length instrs
  804.          fun iter i = if i = len then ()
  805.             else (e_emitInstr (V.sub(instrs,i)); iter (i+1))
  806.            in
  807.            iter 0
  808.            end
  809.        fun emitBlk [] = ()
  810.      | emitBlk (SCHEDBLK instrs::blks) = (emitInstructions instrs;
  811.                           emitBlk blks)
  812.      | emitBlk (DATABLK dl::rest) = (emitDataList dl; emitBlk rest)
  813.      | emitBlk _ = (ErrorMsg.impossible "[Coder.finish.emitBlk]")
  814.        fun schedSize ([],acc) = acc
  815.      | schedSize (SCHEDBLK instrs::blks,acc) = 
  816.          schedSize(blks,acc+4*V.length instrs)
  817.      | schedSize (DATABLK dl::blks,acc) = 
  818.          schedSize(blks,acc+dataListSize dl)
  819.      | schedSize _ = error "Coder.finish.sched'dSize:"
  820.  
  821.        val schedBlocks = sched (mkBasicBlocks(!codeList before codeList:=[]))
  822.        val _ = adjustLow schedBlocks
  823.      in
  824.      E.init (schedSize(schedBlocks,0));
  825.      emitBlk schedBlocks;
  826.      reset()
  827.      end (* finish *)
  828.  
  829. val finish = fn x =>
  830.        let open System.Timer
  831.        val timer = start_timer()
  832.        val z = finish x
  833.        val time = check_timer timer
  834.     in System.Stats.update(System.Stats.schedule, time);
  835.            CompUtil.infomsg "schedule" time;
  836.        z
  837.        end
  838. end
  839.  
  840.